package com.csi.jf.crucible.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.activation.DataHandler;
import org.apache.log4j.Logger;


public class FileUtils {

    public static Logger logger = Logger.getLogger(FileUtils.class);

   /* private static String appDir = "/";*/

   /* public static String getAppDir() {
        // 取得系统的类路径
        String classPath = FileUtils.class.getResource("/").getPath();

        // 获取到系统的部署目录
        int iIndex = classPath.indexOf("WEB-INF");
        appDir = classPath.substring(1, iIndex);

        System.out.println("1:"
                + Thread.currentThread().getContextClassLoader()
                        .getResource(""));

        System.out.println("2:"
                + FileUtils.class.getClassLoader().getResource(""));

        System.out.println("3:" + ClassLoader.getSystemResource(""));
        System.out.println("4:" + FileUtils.class.getResource(""));
        System.out.println("5:" + FileUtils.class.getResource("/"));
        // Class文件所在路径
        System.out.println("6:" + new File("/").getAbsolutePath());
        System.out.println("7:" + System.getProperty("user.dir"));

        return appDir;
    }*/

    /**
     * 获取文件列表
     * 
     * @param String
     *            fileDir 获取文件的目录
     * @return 文件数组
     */
    /*public static File[] getFileList(String fileDir) {
        File dir = new File(fileDir);
        for (String children : dir.list()) {
            System.out.println(children);
        }
        return dir.listFiles();
    }*/

    /**
     * 读取源文件字符数组
     * 
     * @param File
     *            file 获取字符数组的文件
     * @return 字符数组
     */
    public static byte[] readFileByte(File file) {
        FileInputStream fis = null;
        FileChannel fc = null;
        byte[] data = null;
        try {
            fis = new FileInputStream(file);
            fc = fis.getChannel();
            data = new byte[(int) (fc.size())];
            fc.read(ByteBuffer.wrap(data));

        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(),e);
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        } finally {
            if (fc != null) {
                try {
                    fc.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(),e);
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(),e);
                }
            }

        }
        return data;
    }

    /**
     * 读取源文件字符数组
     * 
     * @param filename
     *            String 文件路径
     * @throws IOException
     * @return byte[] 文件内容
     */
    public static byte[] readFileByte(String filename) throws IOException {

        if (filename == null || filename.equals("")) {
            throw new NullPointerException("无效的文件路径");
        }
        File file = new File(filename);
        long len = file.length();
        byte[] bytes = new byte[(int) len];

        BufferedInputStream bufferedInputStream = new BufferedInputStream(
                new FileInputStream(file));
        int r = bufferedInputStream.read(bytes);
        if (r != len){
            throw new IOException("读取文件不正确");
        }
        bufferedInputStream.close();

        return bytes;

    }

    /**
     * 字符数组写入文件
     * 
     * @param byte[] bytes 被写入的字符数组
     * @param File
     *            file 被写入的文件
     * @return 字符数组
     */
    public static String writeByteFile(byte[] bytes, File file) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(bytes);
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(),e);
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(),e);
                }
            }
        }
        return "success";
    }

    /**
     * 移动指定文件夹内的全部文件,(剪切移动)
     * 
     * @param fromDir
     *            要移动的文件目录
     * @param toDir
     *            目标文件目录
     * @param errDir
     *            出错文件目录
     * @throws Exception
     */
    public static void moveFile(String fromDir, String toDir, String errDir) {
        try {
            // 目标文件目录
            File destDir = new File(toDir);
            if (!destDir.exists()) {
                destDir.mkdirs();
            }
            // 开始文件移动
            for (File file : new File(fromDir).listFiles()) {
                if (file.isDirectory()) {
                    moveFile(file.getAbsolutePath(), toDir + File.separator
                            + file.getName(), errDir);
                    file.delete();
                    logger.info("文件夹" + file.getName() + "删除成功");
                } else {
                    File moveFile = new File(toDir + File.separator
                            + file.getName());
                    if (moveFile.exists()) {
                        moveFileToErrDir(moveFile, errDir);// 转移到错误目录
                    }
                    file.renameTo(moveFile);
                    logger.info("文件" + moveFile.getName() + "转移到错误目录成功");
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        } 
    }

    /**
     * 移动文件夹到指定目录下
     * 
     * @param fromDir
     * @param toDir
     */
    public static void moveFile2(String fromDir, String toDir) {
        // 目标文件目录
        File destDir = new File(toDir);
        if (!destDir.exists()) {
            destDir.mkdirs();
        }
        // 开始文件移动
        File[] files = new File(fromDir).listFiles();
        for (File file : files) {
            if (file.isFile()) {
                String toFile = destDir + File.separator + file.getName();
                file.renameTo(new File(toFile));
            }
        }

    }

    // 删除文件夹
    // param folderPath 文件夹完整绝对路径
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); // 删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            myFilePath.delete(); // 删除空文件夹
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
    }

    // 删除指定文件夹下所有文件
    // param path 文件夹完整绝对路径
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);// 再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    private static void moveFileToErrDir(File moveFile, String errDir) {
        int i = 0;
        String errFile = errDir + File.separator + "rnError"
                + moveFile.getName();
        while (new File(errFile).exists()) {
            i++;
            errFile = errDir + File.separator + i + "rnError"
                    + moveFile.getName();
        }
        moveFile.renameTo(new File(errFile));
    }

    /**
     * 从输入流获取字节数组
     * 
     * @param
     */
    public static byte[] getFileByte(InputStream in) {
        ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
        try {
            copy(in, out);
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        }
        return out.toByteArray();

    }

    /**
     * 从输入流输出到输出流
     * 
     */
    private static void copy(InputStream in, OutputStream out)
            throws IOException {

        try {
            byte[] buffer = new byte[4096];
            int nrOfBytes = -1;
            while ((nrOfBytes = in.read(buffer)) != -1) {
                out.write(buffer, 0, nrOfBytes);
            }
            out.flush();
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                logger.error(ex.getMessage(),ex);
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                logger.error(ex.getMessage(),ex);
            }
        }

    }

    // DataHandler写入文件
    public static boolean writeDataHandlerToFile(DataHandler attachinfo,
            String filename) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(filename);
            writeInputStreamToFile(attachinfo.getInputStream(), fos);
            fos.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return false;
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    logger.error(e.getMessage(),e);
                }
            }
        }
        return true;
    }

    private static void writeInputStreamToFile(InputStream is, OutputStream os)
            throws Exception {
        int n = 0;
        byte[] buffer = new byte[8192];
        while ((n = is.read(buffer)) > 0) {
            os.write(buffer, 0, n);
        }
    }

    /**
     * 删除单个文件
     * 
     * @param fileName
     *            被删除文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        if (file.isFile() && file.exists()) {
            file.delete();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 根据链接获取头像文件
     * 
     * @param path
     * @return
     */
    public static InputStream getFileByUrl(String path) throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 利用HttpURLConnection对象,我们可以从网络中获取网页数据.
        conn.setDoInput(true);
        conn.connect();
        return conn.getInputStream(); // 得到网络返回的输入流
    }

    /**
     * 根据链接获取头像文件
     * 
     * @param SONAR_URL
     * @return
     */
    public static InputStream getFileByUrl(URL url) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 利用HttpURLConnection对象,我们可以从网络中获取网页数据.
        conn.setDoInput(true);
        conn.connect();
        return conn.getInputStream(); // 得到网络返回的输入流
    }

    public static String getFileType(String filePath) throws IOException {
        FileType type = FileTypeJudge.getType(filePath);
        return type.name();
    }

    public static String getFileType(File file) throws IOException {
        FileType type = FileTypeJudge.getType(file);
        if(type==null){
            return null;
        }
        return type.name();
    }
    
    public static boolean validateZipType(String type){
        if(type.equals(FileType.ZIP.name())||type.equals(FileType.RAR.name())){
            return true;
        }
        return false;
    }
    
    /**
     * 解压缩文件
     * @param srcFileName
     * @param destPath
     */
    public static void unzip(String srcFileName,String destPath) {
        final int BUFFER = 2048;
        try {
            ZipFile zipFile = new ZipFile(srcFileName);
            Enumeration emu = zipFile.entries();
            int i=0;
            while(emu.hasMoreElements()){
                ZipEntry entry = (ZipEntry)emu.nextElement();
                //会把目录作为一个file读出一次，所以只建立目录就可以，之下的文件还会被迭代到。
                if (entry.isDirectory())
                {
                    new File(destPath + entry.getName()).mkdirs();
                    continue;
                }
                BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
                File file = new File(destPath + entry.getName());
                //加入这个的原因是zipfile读取文件是随机读取的，这就造成可能先读取一个文件
                //而这个文件所在的目录还没有出现过，所以要建出目录来。
                File parent = file.getParentFile();
                if(parent != null && (!parent.exists())){
                    parent.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(fos,BUFFER);           
                
                int count;
                byte data[] = new byte[BUFFER];
                while ((count = bis.read(data, 0, BUFFER)) != -1)
                {
                    bos.write(data, 0, count);
                }
                bos.flush();
                bos.close();
                bis.close();
            }
            zipFile.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
